<?php
/**
 * @description : operating to oauth databases;
 * @class-name  : OAuthDBModel()
 * @author      : stephen.mo
 * @date        : 2010/07/12
 */
class OAuthModel {/*{{{*/
    private $config;
    private $writer;
    private $reader;
    private $mem;
    
    /**
     * @method-name : __construct().
     * @parameter   : NULL.
     * @description : construct this class.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function __construct() {/*{{{*/
        $this->reader = DBConnPoolFactory::getInstance()->getConnPool(OAuthModelConfig::DATABASE_CONFIG_PATH)->getReadConn();
        $this->writer = DBConnPoolFactory::getInstance()->getConnPool(OAuthModelConfig::DATABASE_CONFIG_PATH)->getWriteConn();
        $this->config = ConfigReaderFactory::getInstance()->getConfigReader(OAuthModelConfig::MEMCACHE_CONFIG_XML)->getConfig();
    }/*}}}*/


    /**
     * @method-name : getInstance().
     * @parameters  : NULL
     * @description : instance the class of OAuthModel().
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    static public function getInstance() {/*{{{*/
        static $instance = null ;
        return $instance ? ($instance) : ($instance = new OAuthModel()) ;
    }/*}}}*/


    /**
     * @method-name : getClient().
     * @parameters  : NULL
     * @description : instance the MSApi Client.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    static public function getClient() {/*{{{*/
        static $client = null ;
        return $client ? ($client) : ($client = new MSApiClient());
    }/*}}}*/
  

    /**
     * @method-name : getPortalClient().
     * @parameters  : NULL.
     * @description : instance an portal service client.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/26
     */
    static public function getPortalClient() {/*{{{*/
        static $portal = null;
        $timeless = true;
        $time_now = $time_shift = time();
        return $portal ? ($portal) : ($portal = new PortalWebServiceClient($timeless,$time_now,$time_shift));
    }/*}}}*/


    /**
     * @method-name : getMcClient().
     * @parameters  : NULL
     * @description : instance the Memcache Client.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/19
     */
    static public function getMcClient() {/*{{{*/
        static $mem_client = null ;
        return $mem_client ? ($mem_client) : ($mem_client = self::getInstance()->initMemcache());
    }/*}}}*/
    
    /**
     * @method-name : initMemcache().
     * @parameters  : NULL
     * @description : init the memcached (addServers).
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/19
     */
    public function initMemcache() {/*{{{*/
        $node = OAuthModelConfig::MEMCACHE_NODE_NAME;
        $sub_node = OAuthModelConfig::MEMCACHE_SUB_NODE_NAME;
        $hosts_obj = $this->config->$node;

        try {
            $this->mem = new Memcache;
        }
        catch (Exception $e) {
            return null;
        }

        //add the memcache server
        foreach ($hosts_obj->$sub_node as $key=>$value) {
            $host = trim($value->host);
            $port = trim($value->port);
            if (!empty($host) && !empty($port)) {
                $this->mem->addServer($host,$port);
            }
        }

        return $this->mem;
    }/*}}}*/


    /**
     * @method-name : getRandCode().
     * @parameters  : NULL
     * @description : get a random code string.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @author      : 2010/07/16
     */
    private function getRandCode() {/*{{{*/
        $mt = microtime();
        $rand = mt_rand();
        return $rand;
    }/*}}}*/


    /**
     * @method-name : getExpireTime().
     * @parameters  : (int)$interval - time of interval,default 5 min.
     * @description : get the expire time for this request token.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    private function getExpireTime($interval=5) {/*{{{*/
        $now_time = time();
        return $now_time+($interval*60);
    }/*}}}*/


    /**
     * @method-name : getConsumer().
     * @parameters  : (string)$tags - the tags name of db field,default 'consumer'.
                      (string)$val  - the value of tags ,when will you search.
     * @description : get the consumer informations
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function getConsumer($tags='consumer',$val) {/*{{{*/
        $result = NULL;
        if (empty($val)) return $result;

        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = 'consumer_key_'.$val;
            $ret = $this->get($key);
            if (!empty($ret)) return $ret;
        }

        $field_name = ($tags=='consumer') ? 'consumer_key' : 'consumer_secret';
        $query = "SELECT consumer_key,consumer_secret FROM ".OAuthModelConfig::TABLE_NAME_OF_CONSUMER.
                 " WHERE $field_name='".$val."'";
        $ps = $this->reader->prepare($query);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        if (!empty($result) && OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = 'consumer_key_'.$val;
            $ret = $this->set($key,$result,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);
        }
        return $result;
    }/*}}}*/
   

    /**
     * @method-name : getToken().
     * @parameters  : (string) $tags - the tags name of db field.
     * @description : get the token 
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function getToken($tags) {/*{{{*/
        $result = NULL;
        //try to get it from mc.
        
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = md5('getToken_'.$tags);
            $ret = $this->get($key);
            //if (!empty($ret)) return serialize($ret);
            if (!empty($ret)) return $ret;
        }
        
        //get it from db.
        $query = "SELECT value FROM ".OAuthModelConfig::TABLE_NAME_OF_GENERIC.
                 " WHERE name=:name ".
                 " LIMIT 1 ";
        $ps = $this->writer->prepare($query);
        $ps->bindValue(':name',$tags);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED && !empty($result)) {
            $key = md5('getToken_'.$tags);
            $val = $result['value'];
            $rev = $this->set($key,$val,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);
        }

        return $result['value'];
    }/*}}}*/
    
    /**
     * @method-name : getExistsAccessToken().
     * @parameters  : (string)$tags - a string ,need to search.
     * @description : get an exists access token
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/20
     */
    public function getExistsAccessToken($tags) {/*{{{*/
        
        //get token from mc.
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED && !empty($tags)) {
            $key_request = md5('e_access_'.$tags);
            $access_token = $this->get($key_request);
            if (!empty($access_token)) {
                $key_access = md5($access_token);
                $access_val = $this->get($key_access);
                if (!empty($access_val)) return $access_val;
            }
        }

        //get data from db. 
        $query = "SELECT access_token FROM ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                 " WHERE request_token=:request_token ".
                 " LIMIT 1";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':request_token',$tags);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        if (!isset($result['access_token']) || empty($result['access_token'])) return FALSE;
        $db_access_token = 'access_'.$result['access_token'];
        
        //get the token value.
        $query = "SELECT value FROM ".OAuthModelConfig::TABLE_NAME_OF_GENERIC.
                 " WHERE name=:name ".
                 " LIMIT 1";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':name',$db_access_token);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $rev_val = $ps->fetch(PDO::FETCH_ASSOC);
        if (!isset($rev_val['value']) || empty($rev_val['value'])) return FALSE;
        $tmp_token = unserialize($rev_val['value']);

        //save the data to mc.
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED && !empty($result)) {
            $key_request = md5('e_access_'.$tags);           
            $val_request = serialize($db_access_token);
            $rev = $this->set($key_request,$val_request,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);

            //save the value of access token.
            $key_token = md5($db_access_token);
            $val_token = serialize($tmp_token);
            $rev = $this->set($key_token,$val_token,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);
        }
        
        return $tmp_token;
    }/*}}}*/


    /**
     * @method-name : setToken().
     * @parameters  : (string)$consumer_key - The consumer key.
                      (string)$tags - The tags.
                      (string)$val - The tags' value.
     * @description : set the token
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function setToken($consumer_key,$tags,$val) {/*{{{*/
        $query = "INSERT INTO ".OAuthModelConfig::TABLE_NAME_OF_GENERIC.
                 " (id,consumer_key,name,value,create_time) ".
                 " VALUES ".
                 " (0,:consumer_key,:tags,:val,:create_time) ";
        $ps = $this->writer->prepare($query);
        $ps->bindValue(':consumer_key',$consumer_key);
        $ps->bindValue(':tags',$tags);
        $ps->bindValue(':val',$val);
        $ps->bindValue(':create_time',date('Y-m-d H:i:s'));
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        return TRUE;
    }/*}}}*/


    /**
     * @method-name : setNonce().
     * @parameters  : (string)$tags - The field's value.
     * @description : set a nonce string.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function setNonce($tags) {/*{{{*/
        $query = "INSERT INTO ".OAuthModelConfig::TABLE_NAME_OF_NONCE.
                 " (id,name,create_time) ".
                 " VALUES ".
                 " (0,:tags,:create_time) ";
        $ps = $this->writer->prepare($query);
        $ps->bindValue(':tags',$tags);
        $ps->bindValue(':create_time',date('Y-m-d H:i:s'));
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        return TRUE;
    }/*}}}*/
  

    /**
     * @method-name : delToken().
     * @parameters  : (string)$tags - The token name.
     * @description : delete a request token when generate a access token.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function delToken($tags) {/*{{{*/
        $query = "DELETE FROM ".OAuthModelConfig::TABLE_NAME_OF_GENERIC.
                 " WHERE name='".$tags."'";
        $ps = $this->writer->prepare($query);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = md5('getToken_'.$tags);
            $rev = $this->delete($key);
        }
        return TRUE;
    }/*}}}*/
    

    /**
     * @method-name : queryItem().
     * @parameters  : (string)$tags - The field's value.
                      (string)$type - The chosen table type. default 'generic' table. 
     * @description : query the tags of generic vars
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function queryItem($tags,$type='generic') {/*{{{*/
        $table_name = ($type=='nonce') ? OAuthModelConfig::TABLE_NAME_OF_NONCE : OAuthModelConfig::TABLE_NAME_OF_GENERIC;
        $query = "SELECT id FROM ".$table_name.
                 " WHERE name=:name ".
                 " LIMIT 1";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':name',$tags);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }

        return ($ps->rowCount()>0) ? TRUE : FALSE;
    }/*}}}*/
    

    /**
     * @method-name : checkIsExistsAuthorizeToken().
     * @parameters  : (string)$request_token - The Request Token String.
     * @description : get the rand_code with an authorized request token. 
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/21
     */
    public function checkIsExistsAuthorizeToken($request_token,$expiry_time=NULL) {/*{{{*/
        //check the val from mc.
        $expiry_time = (empty($expiry_time)) ? OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60 : $expiry_time*60;
        $tmp_key = md5('exists_authorized_'.$request_token);
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $values = $this->get($tmp_key);
            if (!empty($values)) return $values;
        }
        
        //check the val from db.
        $query = "SELECT rand_code FROM ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                 " WHERE request_token=:request_token ".
                 " LIMIT 1 ";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':request_token',$request_token);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $result = $ps->fetch(PDO::FETCH_ASSOC);

        //save val to mc.
        if (!empty($result) && OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $values = $result['rand_code'];
            $ref = $this->set($tmp_key,$values,$expiry_time);
        }
        return $result['rand_code'];
    }/*}}}*/
    
    /**
     * @method-name : getConsumerKeyByToken().
     * @parameters  : (string)$token_value - The Token string.
     * @parameter   : (string)$expiry_time - what time is expiry time.
     * @description : get the consumer key with an token string.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/22
     */
    public function getConsumerKeyByToken($token_value,$expiry_time=NULL) {/*{{{*/
        $expiry_time = (empty($expiry_time)) ? OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60 : $expiry_time;
        $tmp_key = md5('consumer_key_'.$token_value);
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $rev = $this->get($tmp_key);
            if (!empty($rev)) return $rev;
        }
        
        //get consumer key from db.
        $query = "SELECT consumer_key FROM ".OAuthModelConfig::TABLE_NAME_OF_GENERIC.
                 " WHERE name=:name_request OR name=:name_access ".
                 " LIMIT 1";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':name_request','request_'.$token_value);
        $ps->bindValue(':name_access','access_'.$token_value);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $result = $ps->fetch(PDO::FETCH_ASSOC);

        //save it to mc.
        if (isset($result['consumer_key']) && !empty($result['consumer_key']) && OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $val = $result['consumer_key'];
            $rev = $this->set($tmp_key,$val,$expiry_time);
        }

        return $result['consumer_key'];
    }/*}}}*/

    /**
     * @method-name : authorizedRequestToken()
     * @parameters  : (array)$requests - request vars.
     * @description : authorized a request token by user id.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function authorizedRequestToken($requests) {/*{{{*/
        $consumer_key  = $requests['consumer_key'];
        $request_token = $requests['request_token'];
        $user_name     = $requests['user_name'];
        $expiry_time   = (isset($requests['expiry_time'])) ? $requests['expiry_time'] : 0;
        $expired_time  = (empty($expiry_time)) ? $this->getExpireTime(OAuthModelConfig::EXPIRE_TIME) : (time()+($expiry_time*60));
        $expiry_time   = (empty($expiry_time)) ? OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60 : $expiry_time*60;
        if (empty($consumer_key) || empty($request_token) || empty($user_name)) return FALSE;

        //check the exists authorized token by request token.
        $rand_code = $this->checkIsExistsAuthorizeToken($request_token);
        
        //add new record.
        if (!$rand_code) {
            $data = new stdclass();
            if (empty($user_name)) return FALSE;
            $data->user = $user_name;
            $rand_code = $this->getRandCode();
            $query = "INSERT INTO ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                     " (id,consumer_key,rand_code,request_token,expire_time,create_time,data) ".
                     " VALUES ".
                     " (0,:consumer_key,:rand_code,:request_token,:expire_time,:create_time,:data) ";
            $ps = $this->writer->prepare($query);
            $ps->bindValue(':consumer_key',$consumer_key);
            $ps->bindValue(':rand_code',$rand_code);
            $ps->bindValue(':request_token',$request_token);
            $ps->bindValue(':expire_time',$expired_time);
            $ps->bindValue(':create_time',date('Y-m-d H:i:s'));
            $ps->bindValue(':data',serialize($data));
            $ret = $ps->execute();
            if (!$ret) {
                return FALSE;
            }
        }
        
        //get val from mc.
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = md5('authorzied_'.$rand_code);
            $val = array('expire_time'=>$expired_time,'request_token'=>$request_token);
            $ret = $this->set($key,$val,$expiry_time);
        }
        
        //genereate a new token.
        $token = (array)unserialize($this->getToken('request_'.$request_token));
        $token['oauth_verify'] = $rand_code;
        return $token;
    }/*}}}*/

    /**
     * @method-name : checkTokenAuthorized().
     * @parameters  : (string)$verify_code - A string of verify.
     * @description : check a token has or not authorized?
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function checkTokenAuthorized($verify_code) {/*{{{*/
        $now_time = time();
        $expire_unit = OAuthModelConfig::EXPIRE_TIME*60;
        $expire_time = $now_time-$expire_unit;
        
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = md5('authorzied_'.$verify_code);
            $ret = $this->get($key);
            if (!empty($ret)) {
                $save_time = $ret['expire_time'];
                if ($save_time>=$expire_time) {
                    return $ret['request_token'];
                }
            }
        }
        
        $query = "SELECT request_token,expire_time FROM ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                 " WHERE rand_code=$verify_code AND expire_time>=:expire_time ".
                 " LIMIT 1 ";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':expire_time',$expire_time);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        if (!empty($result) && OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = md5('authorzied_'.$verify_code);
            $ret = $this->set($key,$result,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60); 
        }
        return (isset($result['request_token'])) ? $result['request_token'] : NULL;

    }/*}}}*/
    
    /**
     * @method-name : getLoginByToken()
     * @parameter   : (string)$access_token
     * @description : get login id by token.
     * @return      : string.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Dec 15,2010
     */
    public function getLoginIdByToken($access_token) {/*{{{*/
        if (empty($access_token)) return FALSE;
        $data = self::verifyAccessToken($access_token);
        if (empty($data) || (isset($data['flag']) && $data['flag']!=1)) return FALSE;
        $rev = (!empty($data['data']['data'])) ? unserialize($data['data']['data']) : NULL;
        if (empty($rev)) return FALSE;
        $login_id = NULL; 
        if (isset($rev->user) && !empty($rev->user)) {
            $userInfo = self::getLoginIdByEmail($rev->user);
            $login_id   = (isset($userInfo->retFlag) && $userInfo->retFlag==1 && isset($userInfo->result->login_id)) ? $userInfo->result->login_id : NULL;
        }
        return $login_id;
    }/*}}}*/

    /**
     * @method-name : checkVerifiable().
     * @parameters  : (string)$consumer_key - A string of consumer public key.
     * @description : check a consumer key is or not need verify?
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/28
     */
    public function checkVerifiable($consumer_key,$expiry_time=NULL) {/*{{{*/
        if (empty($consumer_key)) return TRUE;
        $expiry_time = (!empty($expiry_time)) ? $expiry_time*60 :  OAuthModelConfig::EXPIRE_TIME*60;

        $key = md5($consumer_key);
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $ret = $this->get($key);
            if (!empty($ret)) return $ret;
        }

        $query = "SELECT verifiable FROM ".OAuthModelConfig::TABLE_NAME_OF_CONSUMER.
                 " WHERE consumer_key=:consumer_key ".
                 " LIMIT 1";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':consumer_key',$consumer_key);
        $ret = $ps->execute();
        if (!$ret) return TRUE;
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED && !empty($result)) {
            $rev = $this->set($key,$result['verifiable'],$expiry_time);
        }
        
        return (isset($result['verifiable'])) ? $result['verifiable'] : TRUE;

    }/*}}}*/

    /**
     * @method-name : verfiyAccessToken().
     * @parameters  : (string)$access_token - A string of access_token.
     * @description : verify access token is verifiable
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/23
     */
    public  function verifyAccessToken($access_token) {/*{{{*/
        if (empty($access_token)) return FALSE;
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = sha1('ver_'.$access_token);
            $ret = $this->get($key);
            if (!empty($ret)) return $ret;
        }

        $expire_time = time();
        $query = "SELECT consumer_key,rand_code,request_token,access_token,expire_time,create_time,data ".
                 " FROM ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                 " WHERE expire_time>:expire_time ".
                 " AND access_token=:access_token ";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':expire_time',$expire_time);
        $ps->bindValue(':access_token',$access_token);
        $ret = $ps->execute();
        if (!$ret) return FALSE;
        if ($ps->rowCount()<=0) return FALSE;
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        $rev_flag = (!empty($result)) ? TRUE : FALSE;
        //save it to memcache.
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED && !empty($result)) {
            $rev = array('flag'=>$rev_flag,'data'=>$result);
            $key = sha1('ver_'.$access_token);
            $ret = $this->set($key,$rev,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);
        }
        return array('flag'=>$rev_flag,'data'=>$result);

    }/*}}}*/

    /**
     * @method-name : updateAuthorized().
     * @parameters  : (string)$param - Token string.
                      (string)$verify_code - The VerifyCode.
                      (string)$request_token - The Request Token.
     * @description : update a authorized request token by access token.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function updateAuthorized($param,$verify_code=NULL,$request_token) {/*{{{*/
        parse_str($param,$token);
        $access_token = $token['oauth_token'];
        if (!empty($verify_code)) {
            $query = "UPDATE ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                     " SET access_token=:access_token ".
                     " WHERE request_token=:request_token AND rand_code=:rand_code ";
            $ps = $this->writer->prepare($query);
            $ps->bindValue(':access_token',$access_token);
            $ps->bindValue(':request_token',$request_token);
            $ps->bindValue(':rand_code',$verify_code);
        }
        else {
            $tmp_consumer_key = $this->getConsumerKeyByToken($request_token);
            $expire_time = $this->getExpireTime(OAuthModelConfig::EXPIRE_TIME);
            $create_time = date('Y-m-d H:i:s');
            $data = serialize(array());

            $query = "REPLACE INTO ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                     " (id,consumer_key,rand_code,request_token,access_token,expire_time,create_time,data) ".
                     " VALUES ".
                     " (0,:consumer_key,:rand_code,:request_token,:access_token,:expire_time,:create_time,:data) ";
            $ps = $this->writer->prepare($query);
            $ps->bindValue(':consumer_key',$tmp_consumer_key);
            $ps->bindValue(':rand_code','000000');
            $ps->bindValue(':request_token',$request_token);
            $ps->bindValue(':access_token',$access_token);
            $ps->bindValue(':expire_time',$expire_time);
            $ps->bindValue(':create_time',$create_time);
            $ps->bindValue(':data',$data);
        }
        
        $ret = $ps->execute();
        return (!$ret) ? FALSE : TRUE;
    
    }/*}}}*/
   
    /**
     * @method-name : getAuthorizedData().
     * @parameters  : (string)$request_token - The Request Token String.
     * @description : get the data informations by requestion token
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function getAuthorizedData($request_token) {/*{{{*/
        if (empty($request_token)) return FALSE;
        $now_time = time();
        $expire_unit = OAuthModelConfig::EXPIRE_TIME*60;
        $expire_time = $now_time-$expire_unit;
        
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = 'authorized_'.$request_token;
            $ret = $this->get($key);
            if (!empty($ret)) { 
                $save_time = $ret['expire_time'];
                if ($save_time>=$expire_time) {
                    return $ret['data'];
                }
                else {
                    return FALSE;
                }
            }
        }
        
        //get data from database.
        $query = "SELECT expire_time,data FROM ".OAuthModelConfig::TABLE_NAME_OF_MS_CONSUMER.
                 " WHERE (request_token=:request_token OR access_token=:access_token) AND expire_time>=:expire_time ".
                 " ORDER BY create_time DESC ".
                 " LIMIT 1";
        $ps = $this->reader->prepare($query);
        $ps->bindValue(':request_token',$request_token);
        $ps->bindValue(':access_token',$request_token);
        $ps->bindValue(':expire_time',$expire_time);
        $ret = $ps->execute();
        if (!$ret) {
            return FALSE;
        }
        if ($ps->rowCount()<=0) return NULL;
        $result = $ps->fetch(PDO::FETCH_ASSOC);
        
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED && !empty($result)) {
            $rev = array('expire_time'=>$result['expire_time'],'data'=>$result['data']);
            $key = 'authorized_'.$request_token;
            $ret = $this->set($key,$rev,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);
        }

        return $result['data'];
    }/*}}}*/
   
    /**
     * @method-name : getOAuthApis().
     * @parameters  : (string)$api_name - The name of api's.
                      (array)$params - The Request Parameters.
     * @description : get the MSApi's value.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/16
     */
    public function getOAuthApis($api_name,$params) {/*{{{*/
        if (empty($api_name)) return FALSE;
        switch($api_name) {
            case 'testOAuthUnverifized'://using for testing.
                $result = array('action'=>'Testing','value'=>'OK,I am a testing string');
                break;
            case 'getMembershipProfile':
                $param = array('login_id'=>$params['db']->user);
                $result = self::getPortalClient()->get('Membership.profile',$param);
                break;
            case 'getPayUserStatus':
                $param = array('login_id'=>$params['db']->user);
                $param['lang'] = (isset($params['req']['lang'])) ? $params['req']['lang'] : 'zh-hant-hk';
                $result = self::getPortalClient()->get('Membership.status',array('login_id'=>$param['login_id']));
                break;
            case 'isPayUser':
                $param = array('login_id'=>$params['db']->user);
                $result = self::getPortalClient()->get('Membership.paymentStatus',$param);
                break;
            case 'chooseMobileNetwork':
                $result = OAuthConfig::MEMBER_CHOOSE_PLAN_URL.'?login_id='.$params['db']->user;
                break;
            case 'getUserSubscribeStatus':
                $login_id = (isset($params['req']['oauth_username'])) ? $params['req']['oauth_username'] : NULL;
                if (!empty($login_id)) {
                    $ret = $this->chkLoginIdStateTmp($login_id);
                    if ($ret != 2) {
                        $result = 0;
                        break;
                    }
                    $result = $this->chkIfUserCanBuyPlan($login_id);
                }
                else {
                    $result = 0;
                }
                break;
            case 'getLoginIdByEmail':
                $email_add = (isset($params['req']['oauth_email'])) ? $params['req']['oauth_email'] : NULL;
                if (empty($email_add)) return -1;
                $result = $this->getLoginIdByEmail($email_add);
                if ($result->retFlag != 1) return -1;
                $rev['retFlag'] = $result->retFlag;
                $rev['loginId'] = ($result->retFlag==1) ? $result->result->login_id : NULL;
                $result = $rev;
                break;
            case 'getUserInfoByLoginId':
                $login_id = (isset($params['req']['oauth_username'])) ? $params['req']['oauth_username'] : NULL;
                $result = $this->getUserInfoByLoginId($login_id);
                if ($result->regFlag != 1) return -1;
                break;
            case 'getLoginIdByAccessToken':
                $email     = (isset($params['db']->user)) ? $params['db']->user : NULL;
                $loginInfo = ($this->chkIsThirdPartyUser($email)) ? $this->getLoginIdByEmail($email) : $this->getUserInfoByLoginId($email);
                if ($loginInfo->retFlag==1) {
                    $rev['retFlag'] = 1;
                    $rev['loginId'] = (isset($loginInfo->result->login_id) && !empty($loginInfo->result->login_id)) ? $loginInfo->result->login_id : NULL;
                }
                if ($loginInfo->retFlag != 1 || empty($rev['loginId'])) {
                    return -1;
                }
                $result = $rev;
                break;
            case 'getUserInfoByAccessToken':
                $login_id = (isset($params['db']->user)) ? $params['db']->user : NULL;
                //$loginInfo = (strpos($login_id,'@')===false) ? $login_id : $this->getLoginIdByEmail($login_id);
                $loginInfo = ($this->chkIsThirdPartyUser($login_id)) ?  $this->getLoginIdByEmail($login_id) : $this->getUserInfoByLoginId($login_id);
                if ($loginInfo->retFlag != 1) return -1; 
                if (isset($loginInfo->retFlag)) {
                    $login_id = ($loginInfo->retFlag==1) ? $loginInfo->result->login_id : NULL;
                }
                if (empty($login_id)) {
                    $result['retFlag'] = 0;
                    $result['result'] = NULL;
                    break;
                }
                $result = $this->getUserInfoByLoginId($login_id);
                break;
            default:
                $result=NULL;
        }//end case

        return json_encode($result);
    }/*}}}*/
    
    /**
     * @method-name : get().
     * @parameters  : (string)$key - The MC key.
     * @description : get the data from memcache server.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/19
     */
    public function get($key) {/*{{{*/
        if (empty($key)) return NULL;
        $result = self::getMcClient()->get($key);
        return $result;
    }/*}}}*/
    
    /**
     * @method-name : set().
     * @parameter   : (strint)$key - The MC key.
     * @parameter   : (mixed)$value - The value of MC key.
     * @parameter   : (int)$expire - The expire time of this key,default 5 min.
     * @parameter   : (int)$flag - flag.
     * @description : set the data to memcache items.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/19
     */
    public function set($key,$value,$expire=5,$flag=0) {/*{{{*/
        if (empty($key) || empty($value)) return FALSE;
        $ret = self::getMcClient()->set($key,$value,$flag,$expire);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : delete().
     * @parameters  : (string)$key - The MC key.
     * @description : delete a memcatch item.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/07/19
     */
    public function delete($key) {/*{{{*/
        if (empty($key)) return FALSE;
        $rev = self::getMcClient()->delete($key);
        return $rev;
    }/*}}}*/

    /**
     * @method-name : addNewConsumer().
     * @parameters  : (obj)$consumer - The consumer informations (name & key & secret & flag).
     * @description : add new consumer key to db.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/04
     */
    public function addNewConsumer($consumer) {/*{{{*/
        if (!is_object($consumer) || (!isset($consumer->name) || !isset($consumer->key) || 
            !isset($consumer->secret) || !isset($consumer->flag)) || 
            empty($consumer->name) || empty($consumer->key) || empty($consumer->secret) || empty($consumer->flag)) return FALSE;

        $query = "INSERT INTO ".OAuthModelConfig::TABLE_NAME_OF_CONSUMER.
                 " (id,consumer_name,consumer_key,consumer_secret,verifiable) ".
                 " VALUES ".
                 " (0,:consumer_name,:consumer_key,:consumer_secret,:verifiable) ";
        $ps = $this->writer->prepare($query);
        $ps->bindValue(':consumer_name',$consumer->name);
        $ps->bindValue(':consumer_key',$consumer->key);
        $ps->bindValue(':consumer_secret',$consumer->secret);
        $ps->bindValue(':verifiable',$consumer->flag);
        $ret = $ps->execute();
        return (!$ret) ? FALSE : TRUE;

    }/*}}}*/
    
    /**
     * @method-name : outputConsumer().
     * @parameters  : (string)$consumer_name - The consumer name tag will you input.
     * @description : output the consumer informations
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/04
     */
    public function outputConusmer($consumer_name=NULL) {/*{{{*/
        $condition = (!empty($consumer_name)) ? "  WHERE consumer_name='".$consumer_name."' " : NULL;
        $query = "SELECT consumer_name,consumer_key,consumer_secret,verifiable FROM ".OAuthModelConfig::TABLE_NAME_OF_CONSUMER.$condition;
        $ps = $this->reader->prepare($query);
        $ret = $ps->execute();
        if (!$ret) return FALSE;
        $result = $ps->fetchAll(PDO::FETCH_ASSOC);
        return $result;
    }/*}}}*/

    /**
     * @method-name : chkUserPassword().
     * @parameter   : (string)$username - Input username or user email.
     * @parameter   : (string)$password - Input password string.
     * @description : check the username/email and password.
     * @authro      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/25
     */
    public function chkUserPassword($username,$password) {/*{{{*/
        if (empty($username) || empty($password)) return FALSE;
        $params = array('login_id'=>$username,'password'=>$password);
        $rev = self::getClient()->restRequest('Member','chkUserPassword',$params);
        return $rev;
    }/*}}}*/


    /**
     * @method-name : QuicklyRegisterMember()
     * @parameter   : (string)$email - the email address.
     * @parameter   : (string)$password - the password string.
     * @parameter   : (string)$lang - default choose language.
     * @parameter   : (string)$p_lang - account list language for email.
     * @description : quickly register a tvb member.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/20
     */
    public function quicklyRegisterMember($email,$password,$lang,$p_lang,$ret_type=0) {/*{{{*/
        $params = array('email'=>$email,'password'=>$password,'lang'=>$p_lang,'ret_type'=>$ret_type);
        $rev = self::getClient()->restRequest('Member','quickRegisterByEmail',$params);
        if ($rev->retFlag) return array('retFlag'=>1);
        //tmp_mapping
        $errorCodeTxt = OPI::$errorCodeTxt[$lang];
        $tmp_mapping  = array('1201'=>'1011','1202'=>'1002','1602'=>'1010');
        $errCode      = $tmp_mapping[$rev->errCode];
        return array('retFlag'=>0,'errCode'=>$errCode,'info'=>$errorCodeTxt[$errCode]);
    }/*}}}*/

    /**
     * @method-name : getPackageListByModel()
     * $parameter   : (string)$model - shop model.
     * @parameter   : (string)$lang  - user's language.
     * @description : get the package list by $model
     * @return      : array
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/24
     */
    public function getPackageListByModel($lang,$model='TVB') {/*{{{*/
        
        //add to cache
        if (OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = 'package_list_'.$lang.$model;
            $ret = $this->get($key);
            if (!empty($ret)) { 
                return $ret;
            }
        }
        
        $lang = (empty($lang)) ? 'zh-hant-hk' : $lang;
        $model = (empty($model)) ? 'TVB' : $model;
        $tmp_shop_id = OAuthModelConfig::getShopIdByModel($model);
        $shop_ids = (!empty($tmp_shop_id)) ? implode(',',$tmp_shop_id) : 0;
        if ($shop_ids==0) {
            $result = self::getPortalClient()->get('package.list',array('lang'=>$lang));
            if (!isset($result['data']) || empty($result['data'])) return NULL;
            $data = array();
            $tmp_data = (array)$result['data'];
        }
        else {
            $result = self::getPortalClient()->get('Package.listByShopID',array('shop_ids'=>$shop_ids,'lang'=>$lang));
            $tmp_data = array();
            $tmp      = array();
            foreach((array)$result as $list) {
                foreach($list as $val) {
                    $pkg_id  = $val['package_id'];
                    $pkg_ver = $val['version_id'];
                    $tmp[$pkg_id][$pkg_ver] = $val;
                }
            }
            foreach($tmp as $list) {
                foreach($list as $val) {
                    $tmp_data[] = $val;
                }
            }
        }
        
        $data = array();
        if (!empty($tmp_data)) {
            foreach($tmp_data as $list) {
                $d_key_v = (!empty($list['title'])) ? $list['title'] : (isset($list['description']) ? $list['description'] : NULL);
                if (trim($d_key_v)=='') continue;
                $package_id       = (isset($list['package_id'])) ? $list['package_id'] : NULL;
                $version_id       = (isset($list['version_id'])) ? $list['version_id'] : NULL;
                $price            = (isset($list['price'])) ? $list['price'] : NULL;
                $currency_code    = (isset($list['currency_code'])) ? $list['currency_code'] : NULL;
                $unit             = (isset($list['unit'])) ? $list['unit'] : NULL;
                $auto_renew       = (isset($list['is_auto_renew'])) ? $list['is_auto_renew'] : NULL;
                $description      = (isset($list['description'])) ? $list['description'] : NULL;
                $duration         = (isset($list['duration'])) ? $list['duration'] : NULL;
                $free_period      = (isset($list['free_period'])) ? $list['free_period'] : NULL;
                $free_period_unit = (isset($list['free_period_unit'])) ? $list['free_period_unit'] : NULL;
                $free_in_advance  = (isset($list['free_in_advance'])) ? $list['free_in_advance'] : NULL;
                //intergration.
                $data[] = array('id'=>$package_id,
                    'title'=>$d_key_v,
                    'version'=>$version_id,
                    'price'=>$price,
                    'currency_code'=>$currency_code,
                    'unit'=>$unit,
                    'auto_renew'=>$auto_renew,
                    'duration'=>$duration,
                    'description'=>$description,
                    'free_period'=>array($free_in_advance,$free_period,$free_period_unit)
                );
            }
        }
        if (!empty($data) && OAuthModelConfig::OPEN_CLOSE_MEMCACHED) {
            $key = 'package_list_'.$lang.$model;
            $ret = $this->set($key,$data,OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60);
        }
        return $data;
    }/*}}}*/
    
    /**
     * @method-name : getAsiaPayUrls().
     * @parameter   : (array)$request - the $_REQUEST vars.
     * @parameter   : (bool)$flag - Is or not after register member.
     * @description : get the paypal's url for Asia
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/25
     */
    public function getAsiaPayUrls($request,$flag=false) {/*{{{*/
        //add to cache
        $ret = self::getClient()->restRequest('MSPay','getPaymentUrls');
        if (!empty($ret)) {
            //get request params.
            $call_back   = (isset($request['call_back'])) ? $request['call_back'] : NULL;
            $lang        = (isset($request['lang'])) ? $request['lang'] : 'zh-hant-hk';
            $p_lang      = (isset($request['p_lang'])) ? $request['p_lang'] : $lang;

            //setting return urls and going do jobs. 
            $domain_url       = OAuthConfig::OAuthDomainUrl($_SERVER);
            //setting paypal urls.
            $base_param_url   = '?callback='.urlencode($call_back).'&lang='.$p_lang; 
            $succ_base_url    = $domain_url.OAuthModelConfig::$payment_successUrl.$base_param_url;
            $fail_base_url    = $domain_url.OAuthModelConfig::$payment_failUrl.$base_param_url;
            $errs_base_url    = $domain_url.OAuthModelConfig::$payment_errorUrl.$base_param_url;

            //assign->vars.
            $ret->successUrl = $succ_base_url;
            $ret->failUrl    = $fail_base_url;
            $ret->errorUrl   = $errs_base_url;
        }
        return (!is_array($ret)) ? (array)$ret : $ret;
    }/*}}}*/

    /**
     * @method-name : chkIfUserCanBuyPlan().
     * @parameter   : (int)$login_id - The user's login-id.
     * @description : check a user's is or not buy plan
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/27
     */
    public function chkIfUserCanBuyPlan($login_id) {/*{{{*/
        if (empty($login_id)) return -1;
        $params = array('login_id'=>$login_id);
        $rev = self::getClient()->restRequest('MSPay','chkIfUserCanBuyPlan',$params);
        return ($rev) ? 0 : 1;
    }/*}}}*/
   
    /**
     * @method-name : getLoginIdByEmail().
     * @parameter   : (string)$email_add - Email Address.
     * @description : get the login id with the email.
     * @return      : array 
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/27
     */
    public function  getLoginIdByEmail($email_add) {/*{{{*/
        $params = array('email'=>$email_add);
        $ret = self::getClient()->restRequest('Member','getUserInfoByEmail',$params);
        return $ret;
    }/*}}}*/
    
    /**
     * @method-name : getUserInfoByLoginId().
     * @parameter   : (string)$login_id - Login Id.
     * @description : get the User info with login id.
     * @return      : array 
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/27
     */
    public function getUserInfoByLoginId($login_id) {/*{{{*/
        //add cache.
        $params = array('login_id'=>$login_id);
        $ret = self::getClient()->restRequest('Member','getUserInfoByLoginId',$params);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : genFormPUKey().
     * @description : gen a PU-key
     * @return      : array
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/27
     */
    public function genFormPUKey() {/*{{{*/ 
        $params['ret_type'] = 0;
        $ret = self::getClient()->restRequest('MSPay','genFormPUKey',$params);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : ReGenFormPUKey(). 
     * @parameter   : (string)$ptoken.
     * @parameter   : (string)$pukey.
     * @description : re-gen a new pukey.
     * @return      : array
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/13
     */
    public function reGenFormPUKey($pukey,$ptoken) {/*{{{*/
        $params = array();
        $params['pukey']  = $pukey;
        $params['ptoken'] = $ptoken;
        $ret = self::getClient()->restRequest('MSPay','reGenFormPUKey',$params);
        return $ret;
    }/*}}}*/
    
    /**
     * @method-name : setFormData().
     * @parameter   : (array)$params - array of parameters
     * @description : set the data to memcache(MSApi)
     * @return      : string
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/27
     */
    public function setFormData($pukey,$ptoken,$fdata) {/*{{{*/
        $params['ptoken'] = $ptoken;
        $params['pukey'] = $pukey;
        $params['fdata'] = json_encode($fdata);
        $params['ret_type'] = 0;
        $ret = self::getClient()->restRequest('MSPay','setFormData',$params);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : getFormData()
     * @parameter   : (string)$pukey  - PUkey
     * @parameter   : (string)$ptoken - ptoken.
     * @description : get the form data by pukey.
     * @return      : mixed
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/02
     */
    public function getFormData($pukey,$ptoken) {/*{{{*/
        $params['ptoken'] = $ptoken;
        $params['pukey'] = $pukey;
        $ret = self::getClient()->restRequest('MSPay','getFormData',$params);
        return $ret;
    }/*}}}*/


    /**
     * @method-name : getCaptchaToken().
     * @parameter   : NULL.
     * @description : get the captcha_token from captcha_info and cookies.
     * @return      : string.
     * @authro      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/27
     */
    public function getCaptchaToken() {/*{{{*/
        $captcha_info = self::getClient()->restRequest('Member','getCaptchaInfo',array());
        $reg['captcha_tokens'] = isset($_COOKIE[$captcha_info->cookieName]) ? $_COOKIE[$captcha_info->cookieName] : NULL;
        return $reg;
    }/*}}}*/

    /**
     * @method-name : chkCaptchaToken().
     * @parameter   : (array)$params - captcha infos
     * @description : check the captcha infos from cookie and user's inputs.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/30
     */
    public function chkCaptchaToken($params) {/*{{{*/
        if (empty($params) || !isset($params['captcha']) || !isset($params['captcha_tokens'])) {
            return FALSE;
        }
        $ret = self::getClient()->restRequest('Member','checkCaptcha',$params);
        if (strtolower($ret)=='ok') {
            return TRUE;
        }
        return FALSE;
    }/*}}}*/

    /**
     * @method-name : isValidCreditCard().
     * @parameter   : (strint)$ccNumber - card's number.
     * @description : check a card's number is correct.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/31
     */
    public function isValidCreditCard($ccNumb) {/*{{{*/
        if(is_numeric($ccNumb)) {
            settype($ccNumb,"string");
            $varLen  = strlen($ccNumb)-1;
            $y = 0;
            $returnStr = array();
            for($i=$varLen;$i>=0;$i--) {
                if($y%2 == 0) {
                    $returnStr[] = $ccNumb{$i};
                }
                else{
                    $ccTemp = $ccNumb{$i}*2;
                    if($ccTemp >= 10) {
                        $ccTempRet = 0;
                        settype($ccTemp,"string");
                        $ccTempVar = strlen($ccTemp);
                        for($x=0;$x<$ccTempVar;$x++) {
                            $ccTempRet += $ccTemp{$x};
                        }
                    }
                    else{
                        $ccTempRet = $ccTemp;
                    }
                    $returnStr[] = $ccTempRet;
                }
                $y++;
            }
            $sumReturn = array_sum($returnStr);
            if($sumReturn % 10 == 0)
                return TRUE;
            else
                return FALSE;

        }
        else{
            return FALSE;
        }
    }/*}}}*/

    /**
     * @method-name : isValidExpiryDate().
     * @parameter   : (string)$expiry_year.
     * @parameter   : (string)$expiry_month.
     * @description : check card's expiry date is correct.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/31
     */
    public function isValidExpiryDate($expiry_year,$expiry_month) {/*{{{*/
        $now_y_m = date('Ym');
        $expiry_y_m = $expiry_year.$expiry_month;
        if ( !checkdate( (int)$expiry_month, 1, (int)$expiry_year)  || ( $expiry_y_m < $now_y_m ) ) {
            return FALSE;
        }
        return TRUE;
    }/*}}}*/

    /**
     * @method-name : getOrderIdOfPayment().
     * @parameter   : (array)$params- an array 
     * @parameter   : (string)$type - which API will you call.
     * @description : get an order id from membership API.
     * @return      : string
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/24
     */
    public function getOrderIdOfPayment($params,$type=NULL) {/*{{{*/
        if (!empty($type) && $type=='free') {
            $ret = self::getClient()->restRequest('MSPay','buyFreePlan',$params);
            return $ret;
        }
        $ret = self::getClient()->restRequest('MSPay','genNewOrderPlan',$params);
        return $ret;
    }/*}}}*/
    
    /**
     * @method-name : payOrderByPaymentGateway().
     * @parameter   : (string)$model - which payment gateway you choice?
     * @parameter   : (string)$order_id - The order id string for the payment.
     * @description : get the payment state & message.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/08/24
     */
    public function payOrderByPaymentGateway($model,$order_id) {/*{{{*/
        if (empty($model) || empty($order_id)) return FALSE;
        $pay_name = 'payOrderBy'.ucwords($model).'Gateway';
        $ret = $this->$pay_name();
        return $ret;
    }/*}}}*/

    /**
     * @method-name : getCaptcha().
     * @parameter   : NULL
     * @description : get captcha info
     * @return      : array
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/01
     */
    public function getCaptcha() {/*{{{*/
        $ret = array();
        $ret = self::getClient()->restRequest('Member','captcha');
        return (array)$ret;
    }/*}}}*/

    /**
     * @method-name : getPkgInfo()
     * @parameter   : (int)$package_id.
     * @parameter   : (int)$package_version.
     * @parameter   : (string)$lang
     * @description : get pkg's type by pkg_id & pkg_version.
     * @return      : object
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/09
     */
    public function getPkgInfo($package_id,$package_version,$lang='zh-hant-hk') {/*{{{*/
        $params = array();
        $params['package_id'] = $package_id;
        $params['version_id'] = $package_version;
        $params['lang']       = $lang;
        $ret = self::getClient()->restRequest('MSPay','getPlanInfo',$params);
        $ret->auto_renew = $ret->is_auto_renew;
        $tmp_free_period = array($ret->free_in_advance,$ret->free_period,$ret->free_period_unit);
        $ret->free_period = $tmp_free_period;

        return $ret;
    }/*}}}*/ 

    /**
     * @method-name : chkEmailIsExist().
     * @parameter   : (string)$email
     * @description : check a email is or not exists.
     * @return      : bool
     * @authro      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/09
     */
    public function chkEmailIsExist($email) {/*{{{*/
        $params = array();
        if (empty($email)) return TRUE;
        $params['email'] = $email;
        $ret = self::getClient()->restRequest('Member','checkEmail',$params);
        if (strtolower($ret)=='ok') {
            return TRUE;
        }
        return FALSE;
    }/*}}}*/

    /**
     * @method-name : successCallBack().
     * @parameter   : (array)$formVals.
     * @description : call back function.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/10
     */
    public function successCallBack($formVals) {/*{{{*/
        $ret = self::getClient()->restRequest('MSPay','successCallBack',$formVals);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : faileCallBack().
     * @parameter   : (array)$formVals.
     * @description : call back function.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/10
     */
    public function failCallBack($formVals) {/*{{{*/
        $ret = self::getClient()->restRequest('MSPay','failCallBack',$formVals);
        return $ret;
    }/*}}}*/
    
    /**
     * @method-name : getUserCurrentPlan().
     * @parameter   : (string)$login_id - user's login id.
     * @parameter   : (string)$lang     - language.
     * @description : get user's current plan by login_id.
     * @return      : array
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/17
     */
    public function getUserCurrentPlan($login_id,$lang) {/*{{{*/
        if (empty($login_id)) return FALSE;
        $params['login_id'] = $login_id;
        $params['lang']     = (empty($lang)) ? 'zh-hant-hk' : $lang;
        $ret = self::getClient()->restRequest('MSPay','getUserCurrentPlan',$params);
        $pkg_id = (isset($ret->package_id)) ? $ret->package_id : NULL;
        $pkg_ver = (isset($ret->version_id)) ? $ret->version_id : NULL;
        $pkg_title = (isset($ret->title)) ? $ret->title : NULL;

        if (empty($pkg_title) && !empty($pkg_id) && !empty($pkg_ver)) {
            $rev = $this->getPkgInfo($pkg_id,$pkg_ver);
            $pkg_title = $rev->title;
        }

        $result['login_id']   = $login_id;
        $result['lang']       = $lang;
        $result['package_id'] = $pkg_id;
        $result['version_id'] = $pkg_ver;
        $result['title']      = $pkg_title;
        return $result;

    }/*}}}*/

    /**
     * @method-name : chkUserIsLogined().
     * @parameter   : (string)$user_name - member's login id of tvb.com.
     * @parameter   : (strint)$phone_imei - phone's IMEI string.
     * @parameter   : (string)$user_name - user name.
     * @description : as user's login_id ,check it is logined.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/24
     */
    public function chkUserIsLogined($user_name,$phone_imei=NULL) {/*{{{*/
        $tmp_key = (empty($phone_imei)) ? md5($user_name) : md5($user_name.'_'.$phone_imei);
        $values  = $this->get($tmp_key);
        if (empty($values)) return FALSE;
        return $values;
    }/*}}}*/
    
    /**
     * @method-name : saveUserInfoToMc().
     * @parameter   : (array)$user_info - users' informations. 
     * @parameter   : (string)$expiry_time - the expired time.unit is minute.
     * @description : save the users' information into memcache.
     * @return      : bool.
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : 2010/09/24
     */
    public function saveUserInfoToMc($user_info,$expiry_time=NULL) {/*{{{*/
        //if (!isset($user_info['request_token']) || !isset($user_info['user'])) return FALSE;
        if (!isset($user_info['login_id']) || empty($user_info['login_id'])) return FALSE;
        $tmp_key     = md5($user_info['login_id']);
        $expiry_time = (empty($expiry_time)) ? OAuthModelConfig::MEMCACHE_EXPIRED_TIME*60 : OAuthModelConfig::SAVE_MEMBER_INFO_ETIME*60;
        $ret = $this->set($tmp_key,$user_info,$expiry_time);
        if (isset($user_info['member_id']) && !empty($user_info['member_id'])) {
            $new_key = md5($user_info['member_id']);
            $new_expire_time = OAuthModelConfig::MOBILE_LOGIN_INFO_EXPIRE_TIME;
            $ret = $this->set($new_key,$user_info,$new_expire_time);
        }
        return $ret;
    }/*}}}*/

     /**
     * @method-name : chkIsThirdPartyUser().
     * @parameter   : (string)$user_name - the user' name string.
     * @description : check the inputs is Third-party user.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Oct 8,2010
     */
    public function chkIsThirdPartyUser($user_name) {/*{{{*/
        $reg_txt = "/^[a-zA-Z0-9\._-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/";
        if (!preg_match($reg_txt,$user_name)) {
            return FALSE;
        }
        return TRUE;
    }/*}}}*/
    
    /**
     * @method-name : loginForMobile().
     * @parameter   : (array)$user_info - include (login_id & password)
     * @description : login in
     * @return      : mixed
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Oct 12,2010
     */
    public function loginForMobile($user_info) {/*{{{*/
        if (!isset($user_info['login_id']) || empty($user_info['login_id'])) return FALSE;
        if (!(isset($user_info['map_from_type']) && !empty($user_info['map_from_type']) && ($user_info['map_from_type']==OAuthModelConfig::PCCW_OAUTH_FROM_TYPE))) {
            if (!isset($user_info['password']) || empty($user_info['password'])) return FALSE;
        }
        $ret = self::getClient()->restRequest('Member','loginForMobile',$user_info);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : chkSSOLoginStatus().
     * @parameter   : (array)$params - include (token string & login_id)
     * @description : check user's login status.
     * @return      : int
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Oct 12,2010
     */
    public function chkSSOLoginStatus($params) {/*{{{*/
        if (!isset($params['token']) || empty($params['token'])) return FALSE;
        if (!isset($params['login_id']) || empty($params['login_id'])) return FALSE;
        $ret = self::getClient()->restRequest('Member','chkSSOLoginStatus',$params);
        return $ret;
    }/*}}}*/
    
    /**
     * @mehtod-name : chkLoginIdStateTmp()
     * @parameter   : (strint)$login_id
     * @description : chk the user is logined.
     * @return      : int
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Oct 12,2010
     */
    public function chkLoginIdStateTmp($login_id) {/*{{{*/
        if (empty($login_id))  return -1;
        $userInfo = $this->chkUserIsLogined($login_id);
        if (empty($userInfo) || empty($userInfo['token'])) return -1; 
        $params['token']    = trim($userInfo['token']);
        $params['login_id'] = trim($login_id);
        $ret = $this->chkSSOLoginStatus($params);
        if ($ret != 2) return -1;
        return $ret;
    }/*}}}*/


    /**
     * @method-name : getLoginIdByUserId().
     * @parameter   : (strint)$user_id - the pccw's user_id.
     * @description : get membership's login_id by pccw's user_id.
     * @return      : string
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Oct 20,2010
     */
    public function getLoginIdByUserId($user_id) {/*{{{*/
        //return 'totoros';
        $params['mapped_id'] = $user_id;
        $params['from_type'] = OAuthModelConfig::PCCW_OAUTH_FROM_TYPE;
        $params['from_device'] = OAuthModelConfig::PCCW_OAUTH_FROM_DEVICE;
        $ret = self::getClient()->restRequest('Member','getMappingLoginId',$params);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : chkH3gUserStatus()
     * @parameter   : (array)$params
     * @description : check a 3.com's user have subscripted or not.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 11,2010
     */
    public function chkH3gUserStatus($params) {/*{{{*/
        if (empty($params)) return FALSE;
        $ret = self::getClient()->restRequest('MSPay','h3gChkStatus',$params);
        return $ret;
    }/*}}}*/
    
    /**
     * @method-name : chkCslUserStatus()
     * @parameter   : (array)$params
     * @description : chekc a csl's user have subscripted or not.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Mar 8,2011
     */
    public function chkCslUserStatus($params) {/*{{{*/
        if (empty($params)) return FALSE;
        $ret = self::getClient()->restRequest('MSPay','cslChkStatus',$params);
        return $ret;
    }/*}}}*/


    /**
     * @method-name : getTvbAuthByLoginId().
     * @parameter   : (array)$params.
     * @description : get a encrypt tvbauth string by login id.
     * @return      : string
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 11,2010
     */
    public function getTvbAuthByLoginId($params) {/*{{{*/
        if (empty($params)) return NULL;
        $ret = self::getClient()->restRequest('MSPay','encrypt',$params);
        //$ret = str_replace('+',' ',str_replace('%7E', '~', rawurlencode($ret)));
        return $ret;
    }/*}}}*/
    

    /**
     * @method-name : h3gPaymentSuccessBack().
     * @parameter   : (array)$params
     * @description : the success back do.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Nov 11,2010
     */
    public function h3gPaymentSuccessBack($params) {/*{{{*/
        if (empty($params)) return FALSE;
        $ret = self::getClient()->restRequest('MSPay','h3gSuccessBack',$params);
        return $ret;
    }/*}}}*/

    
    /**
     * @method-name : cslPaymentSuccessBack().
     * @parameter   : (array)$params
     * @description : when success callback to do it.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Mar 8,2011
     */
    public function cslPaymentSuccessBack($params) {/*{{{*/
        if (empty($params)) return FALSE;
        $ret = self::getClient()->restRequest('MSPay','cslSuccessBack',$params);
        return $ret;
    }/*}}}*/

    /**
     * @method-name : forgetPassword().
     * @parameter   : (array)$params
     * @description : send a email and help you to find your password.
     * @return      : bool 
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Dec 8,2010
     */
    public function forgetPassword($params) {/*{{{*/
        if (empty($params)) return FALSE;
        if (empty($params['email'])) return FALSE;
        $ret = self::getClient()->restRequest('Member','forgetPassword',$params);
        if ($ret=='sent_succ') {
            return TRUE;
        }
        return FALSE;
    }/*}}}*/

    /**
     * @method-name : buyH3GPlanForWifi
     * @parameter   : (array)$params
     * @description : buy a plan for H3G gateway with wifi .
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Dec 20,2010
     */
    public function buyH3GPlanForeifi($params) {/*{{{*/
        if (empty($params)) return FALSE;
        $rev = self::getClient()->restRequest('MSPay','h3gBill', $params);
        return $rev;
    }/*}}}*/

    /**
     * @method-name : getH3GMsisdnForWifi
     * @parameter   : encrpt string.
     * @description : decrpt a string for msisdn.
     * @return      : string
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Dec 20,2010
     */
    public function getH3GMsisdnForWifi($string) {/*{{{*/
        if (empty($string)) return NULL;
        $params['source'] = $string;
        $rev = self::getClient()->restRequest('MSPay','h3gDecrypt', $params);
        if (!empty($rev)) {
            $zone_code = substr($rev,0,3);
            $rev = ($zone_code==OAuthModelConfig::AREA_TELPHONE_OF_HONGKONG) ? $rev : OAuthModelConfig::AREA_TELPHONE_OF_HONGKONG.$rev;
        }
        return $rev;
    }/*}}}*/

    /**
     * @method-name : logoutForMobile()
     * @parameters  : (array)$params - include $login_id and $token.
     * @description : logout for mobile with login id.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Jan 18,2011
     */
    public function logoutForMobile($params) {/*{{{*/
        if (!isset($params['login_id']) || empty($params['login_id'])) return FALSE;
        if (!isset($params['token']) || empty($params['token'])) return FALSE;
        $rev = self::getClient()->restRequest('Member','logoutForMobile',$params);
        return $rev;
    }/*}}}*/

    
    /**
     * @method-name : h3gCheckByApi()
     * @parameter   : (string)$msisdn - h3g user's msisdn.
     * @parameter   : (string)$login_id - member's login id.
     * @description : check the h3g Subcribe from remote by 3G.
     * @return      : bool
     * @author      : stephen.mo <stephen.mo@achievo.com>
     * @date        : Mar 11,2011
     */
    public function h3gCheckByApi($msisdn,$login_id) {/*{{{*/
        if (empty($msisdn)) return FALSE;
        $params = array();
        $params['msisdn'] = $msisdn;
        $params['login_id'] = $login_id;
        $rev = self::getClient()->restRequest('MSPay','h3gCheckByApi',$params);
        return $rev;
    }/*}}}*/






}/*}}}*/

?>
